package com.example.backend.service;

import com.example.backend.domain.entity.Ticket;
import com.example.backend.domain.entity.TicketHistory;
import com.example.backend.domain.entity.User;
import com.example.backend.domain.enums.TicketActionType;
import com.example.backend.repository.TicketHistoryRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.List;

@Service
@Transactional
public class TicketHistoryService {
    
    private static final Logger log = LoggerFactory.getLogger(TicketHistoryService.class);

    @Autowired
    private TicketHistoryRepository ticketHistoryRepository;

    /**
     * 创建工单历史记录
     * 使用 REQUIRES_NEW 事务传播机制，即使主事务回滚，历史记录也会保留
     * 注意：为了保证主业务不受影响，调用此方法应该在 try-catch 中
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public TicketHistory createHistory(Ticket ticket, User operator, TicketActionType actionType, 
                                     String oldValue, String newValue, String fieldName, String description) {
        String historyId = "HIST-" + System.currentTimeMillis();
        
        try {
            log.info("[{}] 创建工单历史记录: ticketId={}, action={}, operator={}", 
                historyId, ticket.getId(), actionType, operator.getUsername());
            
            TicketHistory history = TicketHistory.builder()
                    .ticket(ticket)
                    .operator(operator)
                    .actionType(actionType)
                    .oldValue(oldValue)
                    .newValue(newValue)
                    .fieldName(fieldName)
                    .description(description)
                    .build();
            
            TicketHistory saved = ticketHistoryRepository.save(history);
            
            log.info("[{}] ✅ 历史记录保存成功: historyId={}", historyId, saved.getId());
            
            return saved;
            
        } catch (Exception e) {
            log.error("[{}] ❌ 创建历史记录失败: {}", historyId, e.getMessage());
            log.error("[{}] 异常详情:", historyId, e);
            // 重新抛出异常，但由于使用了REQUIRES_NEW，不会影响主事务
            throw new RuntimeException("创建历史记录失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取工单的历史记录
     */
    @Transactional(readOnly = true)
    public List<TicketHistory> getTicketHistory(Long ticketId) {
        return ticketHistoryRepository.findByTicketIdOrderByCreatedAtDesc(ticketId);
    }

    /**
     * 分页获取工单历史记录
     */
    @Transactional(readOnly = true)
    public Page<TicketHistory> getTicketHistory(Long ticketId, Pageable pageable) {
        return ticketHistoryRepository.findByTicketIdOrderByCreatedAtDesc(ticketId, pageable);
    }

    /**
     * 获取特定类型的工单历史记录
     */
    @Transactional(readOnly = true)
    public List<TicketHistory> getTicketHistoryByActionType(Long ticketId, TicketActionType actionType) {
        return ticketHistoryRepository.findByTicketIdAndActionTypeOrderByCreatedAtDesc(ticketId, actionType);
    }

    /**
     * 获取时间范围内的工单历史记录
     */
    @Transactional(readOnly = true)
    public List<TicketHistory> getTicketHistoryByDateRange(Long ticketId, Instant startDate, Instant endDate) {
        return ticketHistoryRepository.findByTicketIdAndDateRange(ticketId, startDate, endDate);
    }

    /**
     * 获取操作员的历史记录
     */
    @Transactional(readOnly = true)
    public Page<TicketHistory> getOperatorHistory(Long operatorId, Pageable pageable) {
        return ticketHistoryRepository.findByOperatorId(operatorId, pageable);
    }

    /**
     * 统计工单的特定操作次数
     */
    @Transactional(readOnly = true)
    public Long countActionByTicketAndType(Long ticketId, TicketActionType actionType) {
        return ticketHistoryRepository.countByTicketIdAndActionType(ticketId, actionType);
    }
}
